// 原生 WebSocket 通信模块，支持自动重连、事件监听、心跳、二进制消息

class WebSocketClient {
  constructor(url, options = {}) {
    this.url = url
    this.ws = null
    this.heartbeatInterval = options.heartbeatInterval || 30000
    this.reconnectInterval = options.reconnectInterval || 5000
    this.maxReconnectAttempts = options.maxReconnectAttempts || 10
    this.reconnectAttempts = 0
    this.heartbeatTimer = null
    this.listeners = {
      open: [],
      message: [],
      close: [],
      error: []
    }
    this.binaryType = options.binaryType || 'arraybuffer'
    this.heartbeatMsg = options.heartbeatMsg || 'ping'
    this.connect()
  }

  connect() {
    this.ws = new WebSocket(this.url)
    this.ws.binaryType = this.binaryType
    this.ws.onopen = (e) => {
      this.reconnectAttempts = 0
      this._emit('open', e)
      this._startHeartbeat()
    }
    this.ws.onmessage = (e) => {
      this._emit('message', e)
    }
    this.ws.onclose = (e) => {
      this._emit('close', e)
      this._stopHeartbeat()
      this._reconnect()
    }
    this.ws.onerror = (e) => {
      this._emit('error', e)
      this._stopHeartbeat()
      this._reconnect()
    }
  }

  send(data) {
    if (this.ws && this.ws.readyState === WebSocket.OPEN) {
      this.ws.send(data)
    }
  }

  close() {
    if (this.ws) {
      this.ws.close()
      this._stopHeartbeat()
    }
  }

  on(event, handler) {
    if (this.listeners[event]) {
      this.listeners[event].push(handler)
    }
  }

  off(event, handler) {
    if (this.listeners[event]) {
      this.listeners[event] = this.listeners[event].filter(fn => fn !== handler)
    }
  }

  _emit(event, ...args) {
    if (this.listeners[event]) {
      this.listeners[event].forEach(fn => fn(...args))
    }
  }

  _startHeartbeat() {
    this._stopHeartbeat()
    this.heartbeatTimer = setInterval(() => {
      if (this.ws && this.ws.readyState === WebSocket.OPEN) {
        this.ws.send(this.heartbeatMsg)
      }
    }, this.heartbeatInterval)
  }

  _stopHeartbeat() {
    if (this.heartbeatTimer) {
      clearInterval(this.heartbeatTimer)
      this.heartbeatTimer = null
    }
  }

  _reconnect() {
    if (this.reconnectAttempts < this.maxReconnectAttempts) {
      this.reconnectAttempts++
      setTimeout(() => {
        this.connect()
      }, this.reconnectInterval)
    }
  }
}

export default WebSocketClient 